<?php

use Hyperf\Context\ApplicationContext;
use Hyperf\Contract\ValidatorInterface;
use Hyperf\Di\Container;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Validation\Contract\ValidatorFactoryInterface;
use Psr\Container\ContainerInterface;

if (!function_exists('app')) {
    /**
     * Get the available container instance.
     *
     * @param string|null $abstract
     * @return mixed|ContainerInterface|Container
     * @noinspection PhpDocMissingThrowsInspection
     */
    function app(string $abstract = null): mixed
    {
        if (is_null($abstract)) {
            return ApplicationContext::getContainer();
        }

        /** @noinspection PhpUnhandledExceptionInspection */
        return ApplicationContext::getContainer()->get($abstract);
    }
}


if (!function_exists('base_path')) {
    /**
     * Get the base path.
     *
     * @param string $path
     * @return string
     */
    function base_path(string $path = ''): string
    {
        return join_paths(BASE_PATH, $path);
    }
}

if (!function_exists('storage_path')) {
    /**
     * Get the storage path
     *
     * @param string $path
     * @return string
     */
    function storage_path(string $path = ''): string
    {
        return join_paths(base_path('storage'), $path);
    }
}

if (!function_exists('join_paths')) {
    /**
     * Join the given paths together.
     *
     * @param string|null $basePath
     * @param string ...$paths
     * @return string
     */
    function join_paths(?string $basePath, ...$paths): string
    {
        foreach ($paths as $index => $path) {
            if (empty($path)) {
                unset($paths[$index]);
            } else {
                $paths[$index] = DIRECTORY_SEPARATOR . ltrim($path, DIRECTORY_SEPARATOR);
            }
        }

        return $basePath . implode('', $paths);
    }
}

if (!function_exists('request')) {
    /**
     * Get an instance of the current request or an input item from the request.
     *
     * @param array|string|null $key
     * @param mixed|null $default
     * @return RequestInterface|string|array|null
     */
    function request(array|string $key = null, mixed $default = null): mixed
    {
        /** @var RequestInterface $request */
        $request = app(RequestInterface::class);
        if (is_null($key)) {
            return $request;
        }

        if (is_array($key)) {
            return $request->inputs($key);
        }

        $value = $request->__get($key);

        return is_null($value) ? value($default) : $value;
    }
}


if (!function_exists('validator')) {
    /**
     * @param array $data
     * @param array $rules
     * @param array $messages
     * @param array $customAttributes
     * @return ValidatorInterface
     * @noinspection PhpDocMissingThrowsInspection
     */
    function validator(array $data, array $rules, array $messages = [], array $customAttributes = [])
    {
        $validationFactory = app(ValidatorFactoryInterface::class);
        return $validationFactory->make($data, $rules, $messages, $customAttributes);
    }
}

if (!function_exists('validate')) {
    /**
     * @param array $data
     * @param array $rules
     * @param array $messages
     * @param array $customAttributes
     * @return array
     */
    function validate(array $data, array $rules, array $messages = [], array $customAttributes = [])
    {
        $validator = validator($data, $rules, $messages, $customAttributes);
        return $validator->validate();
    }
}

if (!function_exists('json')) {
    /**
     * @param mixed $data
     * @param int $flags
     * @param int $depth
     * @return false|string
     */
    function json($data, int $flags = 0, int $depth = 512)
    {
        return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | $flags, $depth);
    }
}
